package com.heu.blood.autologous.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heu.blood.autologous.dao.BloodApplicationAutologousDao;
import com.heu.blood.autologous.dao.BloodApplicationItemAutologousDao;
import com.heu.blood.autologous.dao.BloodCollectAutologousDao;
import com.heu.blood.autologous.dao.BloodInformationAutologousDao;
import com.heu.blood.autologous.dictenum.ApplicationStateAutologousEnum;
import com.heu.blood.autologous.dictenum.CollectStateEnum;
import com.heu.blood.autologous.dictenum.FlowStateEnum;
import com.heu.blood.autologous.entity.*;
import com.heu.blood.autologous.exception.AutologousExceptionEnum;
import com.heu.blood.autologous.service.BloodApplicationAutologousService;
import com.heu.blood.autologous.service.BloodApplicationItemAutologousService;
import com.heu.blood.autologous.vo.*;
import com.heu.blood.common.Constant.ConstantData;
import com.heu.blood.common.enums.ApplicationAutologousVerifyStateEnum;
import com.heu.blood.common.enums.BloodApplicationAutologousEnum;
import com.heu.blood.common.enums.OperateStateEnum;
import com.heu.blood.common.utils.GenerateNumberBySnowFlake;
import com.heu.blood.common.utils.PageUtils;
import com.heu.blood.common.utils.Query;
import com.heu.blood.examine.dao.OperateExamineDao;
import com.heu.blood.examine.entity.OperateExamineEntity;
import com.heu.blood.examine.service.OperateExamineService;
import com.heu.blood.globalExceptionHandler.MyException;
import com.heu.blood.match.exception.TimeException;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service("bloodApplicationAutologousService")
public class BloodApplicationAutologousServiceImpl extends ServiceImpl<BloodApplicationAutologousDao, BloodApplicationAutologousEntity> implements BloodApplicationAutologousService {


    @Autowired
    BloodApplicationItemAutologousDao bloodApplicationItemAutologousDao;

    @Autowired
    private BloodApplicationAutologousDao bloodApplicationAutologousDao;

    @Autowired
    private BloodCollectAutologousDao bloodCollectAutologousDao;

    @Autowired
    private BloodInformationAutologousDao bloodInformationAutologousDao;

    @Autowired
    private BloodApplicationItemAutologousService bloodApplicationItemAutologousService;

    @Autowired
    private OperateExamineService operateExamineService;

    @Autowired
    private OperateExamineDao operateExamineDao;

    @Override
    public PageUtils queryPage(BloodApplicationAutologousSelectVo bloodApplicationAutologousSelectVo) {
        // 校验时间
        if (bloodApplicationAutologousSelectVo.getStartTime() != null
                && bloodApplicationAutologousSelectVo.getEndTime() != null
                && bloodApplicationAutologousSelectVo.getStartTime().after(bloodApplicationAutologousSelectVo.getEndTime())) {
            throw new MyException(TimeException.TIME_OUTLINE);
        }

        Map<String,Object> params = new HashMap<>();
        params.put("limit", bloodApplicationAutologousSelectVo.getLimit());
        params.put("page", bloodApplicationAutologousSelectVo.getPage());
        LambdaQueryWrapper<BloodApplicationAutologousEntity> queryWrapper = Wrappers.lambdaQuery(BloodApplicationAutologousEntity.class);

        queryWrapper.ge(bloodApplicationAutologousSelectVo.getStartTime() != null, BloodApplicationAutologousEntity::getGmtCreate, bloodApplicationAutologousSelectVo.getStartTime())
                .le(bloodApplicationAutologousSelectVo.getEndTime() != null, BloodApplicationAutologousEntity::getGmtCreate, bloodApplicationAutologousSelectVo.getEndTime())
                .like(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getApplicationId()),BloodApplicationAutologousEntity::getApplicationId, bloodApplicationAutologousSelectVo.getApplicationId())
                .like(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getMedicalRecordNumber()),BloodApplicationAutologousEntity::getMedicalRecordNumber, bloodApplicationAutologousSelectVo.getMedicalRecordNumber())
                .like(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getPatientName()),BloodApplicationAutologousEntity::getPatientName, bloodApplicationAutologousSelectVo.getPatientName())
                .like(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getAppliedDoctorName()),BloodApplicationAutologousEntity::getAppliedDoctorName, bloodApplicationAutologousSelectVo.getAppliedDoctorName());
        queryWrapper.orderByDesc(BloodApplicationAutologousEntity::getGmtCreate);
        IPage<BloodApplicationAutologousEntity> page = this.page(
                new Query<BloodApplicationAutologousEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public int updateApplication(BloodApplicationAutologousVo bloodApplicationAutologous) {

        BloodApplicationAutologousEntity bloodApplicationAutologousEntity = new BloodApplicationAutologousEntity();
        BeanUtils.copyProperties(bloodApplicationAutologous,bloodApplicationAutologousEntity);
        this.updateById(bloodApplicationAutologousEntity);
        // 在这去更新每一个子项
        List<BloodApplicationItemAutologousEntity> applicationItems = bloodApplicationAutologous.getApplicationItems();
        for(BloodApplicationItemAutologousEntity item : applicationItems){
            BloodApplicationItemAutologousEntity byId = bloodApplicationItemAutologousService.getById(item);
            if(byId == null){
                // 把申请的id给附着上,数据库中不存在该子项，则说明该子项是新的数据，需要插入到数据库中
                item.setApplicationId(bloodApplicationAutologous.getApplicationId());
                bloodApplicationItemAutologousService.save(item);
            }else{
                bloodApplicationItemAutologousService.updateById(item);
            }
        }
        return 0;
    }


    @Override
    @Transactional
    public int removeApplicationAndItemsByIds(List<BloodApplicationAutologousEntity> bloodAutologousApplication) {
        if(bloodAutologousApplication.size() == 0){
            return 1;
        }
        List<Long> deleteIds = new ArrayList<>();
        // 构建删除申请详情的wrapper
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> queryWrapper = new LambdaQueryWrapper<>();
        for(int i = 0;i < bloodAutologousApplication.size();i++){
            BloodApplicationAutologousEntity cur = bloodAutologousApplication.get(i);
            deleteIds.add(cur.getId());
            if(i == 0){
                queryWrapper.eq(Strings.isNotBlank(cur.getApplicationId()),BloodApplicationItemAutologousEntity::getApplicationId,cur.getApplicationId());
            }else{
                queryWrapper.or().eq(Strings.isNotBlank(cur.getApplicationId()),BloodApplicationItemAutologousEntity::getApplicationId,cur.getApplicationId());
            }

        }
        // 根据id删除所有的申请单里面的数据
        this.removeByIds(deleteIds);
        // 根据申请单id删除所有的东西
        bloodApplicationItemAutologousDao.delete(queryWrapper);

        return 0;
    }

    @Override
    public BloodApplicationAutologousEntity selectBloodApplicationAutologousByApplicationId(String applicationId) {
        if(applicationId == null || "".equals(applicationId)) return null;
        LambdaQueryWrapper<BloodApplicationAutologousEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationAutologousEntity::getApplicationId,applicationId);
        BloodApplicationAutologousEntity bloodApplicationAutologousEntity = bloodApplicationAutologousDao.selectOne(queryWrapper);
        return bloodApplicationAutologousEntity;
    }

    @Override
    public int saveApplication(BloodApplicationAutologousVo bloodApplicationAutologous) {
        // 雪花算法生成的输血id
        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.APPLICATION_Autologous_NO_WORK_ID, ConstantData.APPLICATION_Autologous_NO_PREFIX);
        BloodApplicationAutologousEntity bloodApplicationAutologousEntity = new BloodApplicationAutologousEntity();
        BeanUtils.copyProperties(bloodApplicationAutologous,bloodApplicationAutologousEntity);
        String applicationId = generateNumberBySnowFlake.genNumberByflag();
        bloodApplicationAutologousEntity.setApplicationId(applicationId);

        bloodApplicationAutologousEntity.setApplicationState(BloodApplicationAutologousEnum.PENDING_BLOOD_COLLECTION.code());
        bloodApplicationAutologousEntity.setVerifyState(ApplicationAutologousVerifyStateEnum.IN_VERIFY.code());

        List<BloodApplicationItemAutologousEntity> applicationItems = bloodApplicationAutologous.getApplicationItems();
        for(BloodApplicationItemAutologousEntity item : applicationItems){
            item.setApplicationId(applicationId);
            item.setCollectState(CollectStateEnum.ITEM_PENDING_BLOOD_COLLECTION.code());

        }

        bloodApplicationItemAutologousService.saveBatch(applicationItems);
        if(applicationItems.size() > 1) {
            bloodApplicationAutologousEntity.setIsSingle(0);
        } else {
            bloodApplicationAutologousEntity.setIsSingle(1);
        }

        List<OperateExamineEntity> examineEntities = bloodApplicationAutologous.getExamineEntities();
        for(int i = 1;i <= examineEntities.size();i++ ){
            OperateExamineEntity cur = examineEntities.get(i - 1);
            // 设置交易类型
            cur.setTradeType(ConstantData.BLOOD_APPLICATION_AUTOLOGOUS);
            // 交易id也要设置进去
            cur.setTradeId(applicationId);
            // 设置状态为待处理
            cur.setOperateState(OperateStateEnum.WAIT.code());
        }
        // 一起塞进去就完事了
        operateExamineService.saveBatch(examineEntities);
        BeanUtils.copyProperties(applicationItems.get(0),bloodApplicationAutologousEntity);

        this.save(bloodApplicationAutologousEntity);
        return 0;
    }

    @Override
    public BloodApplicationAutologousVo applicationInfo(String applicationId) {
        BloodApplicationAutologousVo res = new BloodApplicationAutologousVo();
//        根据applicationId查询出来本条申请单
        LambdaQueryWrapper<BloodApplicationAutologousEntity> applicationWrapper = new LambdaQueryWrapper<>();
        applicationWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationAutologousEntity::getApplicationId,applicationId);
        BloodApplicationAutologousEntity applicationRes = bloodApplicationAutologousDao.selectOne(applicationWrapper);
        BeanUtils.copyProperties(applicationRes, res);
//        根据applicationId查询出来的详细信息
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> applicationItemWrapper = new LambdaQueryWrapper<>();
        applicationItemWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationItemAutologousEntity::getApplicationId,applicationId);
        List<BloodApplicationItemAutologousEntity> bloodApplicationItemRes = bloodApplicationItemAutologousDao.selectList(applicationItemWrapper);

        // 在这获取所有的申请单审批信息
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(applicationId),OperateExamineEntity::getTradeId,
                applicationId);
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        res.setExamineEntities(operateExamineEntities);

        // 构造最终结果
        res.setApplicationItems(bloodApplicationItemRes);
        return res;
    }

    @Override
    public BloodApplicationAutologousVo getApplicationInfo(BloodApplicationAutologousVo bloodApplicationAutologousVo) {
        String applicationId = bloodApplicationAutologousVo.getApplicationId();
        BloodApplicationAutologousVo res = new BloodApplicationAutologousVo();
//        根据applicationId查询出来本条申请单
        LambdaQueryWrapper<BloodApplicationAutologousEntity> applicationWrapper = new LambdaQueryWrapper<>();
        applicationWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationAutologousEntity::getApplicationId,applicationId);
        BloodApplicationAutologousEntity applicationRes = bloodApplicationAutologousDao.selectOne(applicationWrapper);
        BeanUtils.copyProperties(applicationRes, res);
//        根据applicationId查询出来的详细信息
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> applicationItemWrapper = new LambdaQueryWrapper<>();
        applicationItemWrapper.eq(Strings.isNotBlank(applicationId),BloodApplicationItemAutologousEntity::getApplicationId,applicationId);
        List<BloodApplicationItemAutologousEntity> bloodApplicationItemRes = bloodApplicationItemAutologousDao.selectList(applicationItemWrapper);

        // 在这获取所有的申请单审批信息
        LambdaQueryWrapper<OperateExamineEntity> examineWrapper = new LambdaQueryWrapper<>();
        examineWrapper.eq(Strings.isNotBlank(applicationId),OperateExamineEntity::getTradeId,
                applicationId);
        List<OperateExamineEntity> operateExamineEntities = operateExamineDao.selectList(examineWrapper);
        res.setExamineEntities(operateExamineEntities);

        // 构造最终结果
        res.setApplicationItems(bloodApplicationItemRes);
        return res;
    }

    public List<BloodApplicationAutologousItemAndCollectVo> getBloodAutologousApplicationAndCollectRecords(String applicationId) {
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> itemQueryWrapper = new LambdaQueryWrapper<>();
        itemQueryWrapper.eq(BloodApplicationItemAutologousEntity::getApplicationId, applicationId);


        List<BloodApplicationItemAutologousEntity> applicationItems = bloodApplicationItemAutologousDao.selectList(itemQueryWrapper);

        if (applicationItems == null || applicationItems.isEmpty()) {
            return Collections.emptyList();
        }

        List<BloodApplicationAutologousItemAndCollectVo> resultList = new ArrayList<>();

        for (BloodApplicationItemAutologousEntity item : applicationItems) {
            Long itemId = item.getId();
            LambdaQueryWrapper<BloodCollectAutologousEntity> collectQueryWrapper = new LambdaQueryWrapper<>();
            collectQueryWrapper.eq(BloodCollectAutologousEntity::getBloodApplicationItemAutologousId, itemId);

            BloodApplicationAutologousItemAndCollectVo vo = new BloodApplicationAutologousItemAndCollectVo();
            vo.setBloodApplicationItemAutologousInfo(item);

            BloodCollectAutologousEntity bloodCollectRecord = bloodCollectAutologousDao.selectOne(collectQueryWrapper);

            if (bloodCollectRecord != null) {
                vo.setBloodCollectAutologousInfo(bloodCollectRecord);
            } else {
                vo.setBloodCollectAutologousInfo(null);
            }
            resultList.add(vo);
        }

        return resultList;
    }
    @Override
    public int generateAutologousApplicationId(BloodApplicationAutologousEntity bloodApplicationAutologousEntity) {
        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.APPLICATION_Autologous_NO_WORK_ID, ConstantData.APPLICATION_Autologous_NO_PREFIX);
        String applicationId = generateNumberBySnowFlake.genNumberByflag();
        bloodApplicationAutologousEntity.setApplicationId(applicationId);
        bloodApplicationAutologousEntity.setApplicationState(ApplicationStateAutologousEnum.PENDING_BLOOD_COLLECTION.value());
        int insert = bloodApplicationAutologousDao.insert(bloodApplicationAutologousEntity);
        return insert;
    }
    @Override
    public AutologousCenterFlowResultVo centFlowList(BloodApplicationAutologousSelectVo bloodApplicationAutologousSelectVo) {
        AutologousCenterFlowResultVo res = new AutologousCenterFlowResultVo();
        LambdaQueryWrapper<BloodApplicationAutologousEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 校验时间
        if (bloodApplicationAutologousSelectVo.getStartTime() != null
                && bloodApplicationAutologousSelectVo.getEndTime() != null
                && bloodApplicationAutologousSelectVo.getStartTime().after(bloodApplicationAutologousSelectVo.getEndTime())) {
            throw new MyException(TimeException.TIME_OUTLINE);
        }
        queryWrapper.ge(bloodApplicationAutologousSelectVo.getStartTime() != null, BloodApplicationAutologousEntity::getGmtCreate, bloodApplicationAutologousSelectVo.getStartTime())
                .le(bloodApplicationAutologousSelectVo.getEndTime() != null, BloodApplicationAutologousEntity::getGmtCreate, bloodApplicationAutologousSelectVo.getEndTime());
        if(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getApplicationState())){
            queryWrapper.like(true,BloodApplicationAutologousEntity::getApplicationState,bloodApplicationAutologousSelectVo.getApplicationState());
        }
        if(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getApplicationId())){
            queryWrapper.like(true,BloodApplicationAutologousEntity::getApplicationId,bloodApplicationAutologousSelectVo.getApplicationId());
        }
       /* if(Strings.isNotBlank(bloodApplicationAutologousSelectVo.getMedicalRecordNumber())){
            queryWrapper.eq(true,BloodApplicationAutologousEntity::getMedicalRecordNumber,bloodApplicationAutologousSelectVo.getMedicalRecordNumber());
        }*/
        // 倒序
        queryWrapper.orderByDesc(BloodApplicationAutologousEntity::getGmtCreate);
        // 查出来列表
        List<BloodApplicationAutologousEntity> list = this.list(queryWrapper);
        // 查询结果为空
        if(list.size() == 0){
            return res;
        }
        res.setEntities(list);
        // 查出当前选择的
        BloodApplicationAutologousEntity curChoose = list.get(0);
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> bloodApplicationItemAutologousEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bloodApplicationItemAutologousEntityLambdaQueryWrapper.eq(Strings.isNotBlank(curChoose.getApplicationId()),BloodApplicationItemAutologousEntity::getApplicationId,curChoose.getApplicationId());
        List<BloodApplicationItemAutologousEntity> bloodApplicationItemAutologousEntities = bloodApplicationItemAutologousDao.selectList(bloodApplicationItemAutologousEntityLambdaQueryWrapper);
        // 赋值好存在的申请单详情项目
        BloodApplicationAutologousVo bloodApplicationAutologousVo = new BloodApplicationAutologousVo();
        BeanUtils.copyProperties(curChoose,bloodApplicationAutologousVo);
        bloodApplicationAutologousVo.setApplicationItems(bloodApplicationItemAutologousEntities);
        res.setChooseEntity(bloodApplicationAutologousVo);
        return res;
    }

    @Override
    public List<ApplicationStateInfoEntity> getBloodApplicationAutologousState(String applicationId) {
        if (applicationId == null || "".equals(applicationId)) return null;
        List<ApplicationStateAutologousEnum> applicationFlow = Arrays.asList(
                ApplicationStateAutologousEnum.BLOOD_APPLICATION_AUTOLOGOUS,
                ApplicationStateAutologousEnum.PENDING_BLOOD_COLLECTION,
                ApplicationStateAutologousEnum.BLOOD_COLLECTED,
                ApplicationStateAutologousEnum.BLOOD_SEND,
                ApplicationStateAutologousEnum.POST_TRANSFUSION_EVALUATION
        );
        LambdaQueryWrapper<BloodApplicationAutologousEntity> bloodApplicationAutologousEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bloodApplicationAutologousEntityLambdaQueryWrapper.eq(Strings.isNotBlank(applicationId), BloodApplicationAutologousEntity::getApplicationId, applicationId);
        BloodApplicationAutologousEntity bloodApplicationAutologousEntity = bloodApplicationAutologousDao.selectOne(bloodApplicationAutologousEntityLambdaQueryWrapper);

        if (bloodApplicationAutologousEntity == null) return null;
        String applicationState = bloodApplicationAutologousEntity.getApplicationState();
        int flag=applicationFlow.indexOf(ApplicationStateAutologousEnum.valueOf(applicationState));

        boolean isCurrent=false;
        List<ApplicationStateInfoEntity> stateInfoEntities=new ArrayList<>();
        for (int i = 0 ; i < applicationFlow.size() ; i++){
            ApplicationStateAutologousEnum state=applicationFlow.get(i);
            ApplicationStateInfoEntity node=new ApplicationStateInfoEntity();
            node.setTitle(state.value());
            if (state.code().equals(ApplicationStateAutologousEnum.BLOOD_APPLICATION_AUTOLOGOUS.code())){
                if (state.code().equals(applicationState)){
                    isCurrent = true;
                }
                node.setStatus(FlowStateEnum.SUCCESS.value());
            } else if (state.code().equals(applicationState)) {
                node.setStatus(FlowStateEnum.SUCCESS.value());
                isCurrent = true;
            } else if (isCurrent && i == flag + 1 ) {
                node.setStatus(FlowStateEnum.FINISH.value());
            } else if (isCurrent){
                node.setStatus(FlowStateEnum.WAIT.value());
            } else {
                node.setStatus(FlowStateEnum.SUCCESS.value());
            }
            stateInfoEntities.add(node);

        }
        return stateInfoEntities;
    }

    @Override
    public BloodApplicationAutologousResultVo getApplicationAndBloodInformationByItemId(Long bloodapplicationItemId) {
        LambdaQueryWrapper<BloodApplicationItemAutologousEntity> bloodApplicationItemAutologousEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bloodApplicationItemAutologousEntityLambdaQueryWrapper.eq( bloodapplicationItemId != null && bloodapplicationItemId > 0, BloodApplicationItemAutologousEntity::getId, bloodapplicationItemId);
        BloodApplicationItemAutologousEntity bloodApplicationItemAutologousEntity = bloodApplicationItemAutologousDao.selectOne(bloodApplicationItemAutologousEntityLambdaQueryWrapper);

        if (bloodApplicationItemAutologousEntity == null) {
            return null;
        }

        LambdaQueryWrapper<BloodInformationAutologousEntity> bloodInformationAutologousEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bloodInformationAutologousEntityLambdaQueryWrapper.eq( bloodapplicationItemId != null && bloodapplicationItemId > 0, BloodInformationAutologousEntity::getBloodApplicationItemId, bloodapplicationItemId);
        BloodInformationAutologousEntity bloodInformationAutologousEntity = bloodInformationAutologousDao.selectOne(bloodInformationAutologousEntityLambdaQueryWrapper);

        BloodApplicationAutologousResultVo bloodApplicationAutologousResultVo=new BloodApplicationAutologousResultVo();
        bloodApplicationAutologousResultVo.setBloodApplicationItemAutologousEntity(bloodApplicationItemAutologousEntity);
        bloodApplicationAutologousResultVo.setBloodInformationAutologousEntity(bloodInformationAutologousEntity);
        if (bloodInformationAutologousEntity != null){
            bloodApplicationAutologousResultVo.setBloodId(bloodInformationAutologousEntity.getBloodId());
        }
        return bloodApplicationAutologousResultVo;
    }
}